import jwt, { type SignOptions, type VerifyErrors } from 'jsonwebtoken';

import { type MyClaims, type BaseClaims, ParsedToken } from './types';

export let signingKey: string = '';

/**
 * Generates a JWT token string for the given claims and key.
 * Equivalent to GenerateToken() in Go.
 */
export function generateToken(claims: BaseClaims, expiresInSeconds?: number): string {
  const currentTime = new Date();

  const options: SignOptions = {
    algorithm: 'HS256',
    notBefore: 0,
    ...(expiresInSeconds ? { expiresIn: expiresInSeconds } : {}),
  };

  // Adds issuedAt
  claims.iat = Math.floor(currentTime.getTime() / 1000);

  return jwt.sign(claims, signingKey, options);
}

/**
 * Validates the given token string.
 * Returns claims and a validity flag.
 * Equivalent to ValidateToken() in Go.
 */
export function validateToken(tokenString: string): ParsedToken {
  const parsedToken = new ParsedToken();
  parsedToken.token = tokenString;

  try {
    const decoded = jwt.verify(tokenString, signingKey) as MyClaims;
    parsedToken.valid = true;
    parsedToken.claims = decoded;

    return parsedToken;
  } catch (err) {
    const e = err as VerifyErrors;

    if (e.name?.toLowerCase() === 'tokenexpirederror') {
      parsedToken.expired = true;
    }

    return parsedToken;
  }
}
